home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
PRUS101
/
FSWAP.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-09-15
|
24KB
|
705 lines
TITLE FSWAP.ASM
; (***************************************************************************
;
; RELEASE 1.00 - as contained in the file
; by Peter Holschbach, 2:2450/660.3, GERMANY
;
; --------------------------------------------
; organized for Fido's PASCAL related echoes
; --------------------------------------------
;
; 09/01/1994 to --/--/---- by Peter Holschbach, 2:2450/660.3, GERMANY
;
;
; As far as third party copyrights are not violated this
; source code is hereby placed to the public domain. Use
; it whatever way you want, but use AT YOUR OWN RISK.
;
; In case you should modify the source rather send your
; modifications to the unit's current organizer (see above for
; NM address) than to spread it on your own. This will help to
; keep the unit updated and grant a certain standard to all
; other users as well.
;
; The unit is currently still under work. So it might greatly
; benefit of your participation.
;
; Those who contributed to the following piece of source,
; listed in alphabethical order:
; ================================================================
; Peter Holschbach ...
; ================================================================
; YOUR NAME WILL APPEAR HERE IF YOU CONTRIBUTE USEFUL SOURCE.
;
; Credits in your own programs are as welcome as unnecessary.
;
;***************************************************************************)
;
; Assembler: tested only with TASM 3.2
; Call: TASM /M3 FSWAP.ASM
;
;***************************************************************************)
.8086 ; OK! the last PC at the world should use it
JUMPS ; use long jumps if needed
LOCALS @@ ; every label started with @@ is local
;-----------------------------------------------------------------------------
PUBLIC SwapExec
;-----------------------------------------------------------------------------
EXTRN DosRetValue : Word ; global variable for return value
EXTRN PrefixSeg : Word
EXTRN SwapFilePath : Byte ; it's a string
;-----------------------------------------------------------------------------
DosBlockSize EQU 0FFF0H ; there are problems to write FFFFh,
; max. FFFAh Bytes will be written.
; ! use ony a size MOD 16 !
IF (DosBlockSize MOD 16) NE 0
ERR "The size of DosBlockSize should be a value MOD 16 !"
ENDIF
EmsPageSize EQU 16 * 1024
;-------------------------- error messages from "SwapExec"
ErrDeviceNotAvailable EQU 0001 ; EMS/XMS not available
ErrSizeCalc EQU 0002 ; start is bigger then last
ErrNotEnoughSpace EQU 0003 ; EMS/XMS/Disk
ErrCantGetSize EQU 0004 ; Disk
ErrCreateTempFile EQU 0005 ; Disk
ErrWriteFile EQU 0006 ; Disk
ErrReadFile EQU 0007 ; Disk
ErrCheckSizeToSave EQU 0008
ErrAllocation EQU 0009
ErrSwapOut EQU 0010
; MSB
ErrMemReduce EQU 11 ; -> LSB = error from DOS
ErrManager EQU 0FFh ; -> MSB = error message from XMS/EMS
;-------------------------- definitions for easy acces
hi EQU (Word PTR 2)
lo EQU (Word PTR 0)
ofst EQU (Word PTR 0)
segm EQU (Word PTR 2)
hidden EQU 2
sys EQU 4
SwapFileAttr EQU hidden+sys
;-----------------------------------------------------------------------------
; The definitoins of some structures
;-----------------------------------------------------------------------------
; ----------- structur to copy data from/to EMS
EMSstrucTyp STRUC
RegionLength DD ? ; length of memory region to copy (in byte)
SourceMemoryTyp DB ? ; 0=conventional memory / 1=EMS
SourceHandle DW ? ; 0=conventional memory
SourceInitialOffset DW ? ; offset in source from which to begin
SourceInitialSegPage DW ? ; segment in source from which to begin
DestMemoryTyp DB ? ; 0=conventional memory / 1=EMS
DestHandle DW ? ; 0=conventional memory
DestInitialOffset DW ? ; offset in destination from which to begin
DestInitialSegPage DW ? ; segment in destination from which to begin
ENDS
; ----------- structure for exec
ExexStrucTyp STRUC
EnvironmSeg DW ? ; 0 = copy parent Environment
ParamString DD ? ; max. 128 Bytes
FCB1 DD ?
FCB2 DD ?
ENDS
; ----------- structur to copy data from/to XMS
XMSstrucTyp STRUC
BytesToMove DD ? ; how many bytes to move
HandleS DW ? ; if source = XMS the handle number
PtrS DD ? ; if source = Memory a Pointer at the beginning
HandleD DW ? ; if destination = XMS the handle number
PtrD DD ? ; if dest. = memory a Pointer at the beginning
ENDS
;-----------------------------------------------------------------------------
; The definitions of some macros
;-----------------------------------------------------------------------------
; --------- simple case macro to CALL depending of a value in AL
Case MACRO CaseVar,destinations,OkAddr
LOCAL @@endcase
count = 0
MOV AL,CaseVar
IRP jumpTo,destinations,OkAddr
LOCAL @@J&count
CMP AL,count
JNE @@J&count
CALL jumpTo
JNC OkAddr
JMP @@endcase
@@J&count:
count = count + 1
ENDM
@@endcase:
ENDM
; --------- copy a pascal string in CS and use "0" as terminator
CopyPascalString MACRO Source,Destination
LOCAL @@emptyString
PUSH DS
LDS SI,Source
MOV AX,SEG Destination
MOV ES,AX
LEA DI,Destination
LODSB ; size of string in AL
CMP AL,0 ; empty string ?
JE @@emptyString
MOV CL,AL
XOR CH,CH ; CX = size
REP_FastMovs
@@emptyString:
XOR AL,AL
STOSB
POP DS
ENDM
; --------- macro to use MOVSW
REP_FastMovs MACRO
LOCAL @@noByteLeft
SHR CX,1
REP MOVSW
JNC @@noByteLeft
MOVSB
@@noByteLeft:
ENDM
;##########################################################################
; and now the first code
;##########################################################################
.MODEL LARGE
.CODE
;--------------------------------------------------
; All variables in CS who are needed after swap out
;--------------------------------------------------
;-------- variables needed for EMS
EMSmovStruc EMSstrucTyp ?
;-------- variables used for XMS
XMSPointer DD ?
;-------- variables for exec
ProgPathName DB 80 DUP (?)
ProgParam DB 128 DUP (?)
nFCB1 DB 16 DUP (?)
nFCB2 DB 16 DUP (?)
ExexStruc ExexStrucTyp {EnvironmSeg=0, ParamString=ProgParam,FCB1=nFCB1,FCB2=nFCB2}
;----------------
myPSP DW ?
MaxSize DW ? ; aktual size of the program
MinSize DW ? ; the minimal size of this program
; in paragraphs
;----------------
EnAdress DD ? ; last Adress to save
Handle DW ? ; then Handle for DISC/EMS/XMS
MethodCS DB ?
RetValue DW ?
SaveSize DD ?
;-------- everything for the stack
SaveSP DW ?
SaveSS DW ?
OriginSP DW ?
OriginSS DW ?
DW 50 DUP (?)
TmpStack LABEL WORD
;----------------------------------------------------------------------------
; the function that must be called from Turbo Pascal
;----------------------------------------------------------------------------
;Function SwapExec (FileName,Parameter : String; LastAdr : Pointer; Method : TSwapMemTyp): Word;
SwapExec PROC PASCAL FAR FileName : DWORD,Parameter : DWORD, LastAdr : DWord, Method : Byte
PUSH DS ; save the datasegment
CALL CopyFromTurbo
MOV AX,ErrCheckSizeToSave ; nothing to save ?
JE Exit1
;--------------- check if memorytyp is available
CASE MethodCS,<CheckXMSDriver,CheckEMSDriver,CheckDiskDriver>,DeviceOK
; -------------- errorhandler "device not available"
DeviceError:
MOV AX,ErrDeviceNotAvailable
JMP Exit1
DeviceOK:
;--------------- allocate memory
CASE MethodCS,<XMSAllocate,EMSAllocate,DiskAllocate>,AlloCationOk
;--------------- allocation error
AllocationError:
MOV AX,ErrAllocation
JMP Exit1
;--------------- swap to memory or disk
AlloCationOk:
MOV Handle,DX ; save the handle
CASE MethodCS,<SwapXms,SwapEMS,SwapDisk>,SwapOk
JMP Exit1
swapError:
;--------------- problem while swapout
CASE MethodCS,<XMSDeAllocate,EMSDeAllocate,DiskDeAllocate>,ProbDealloc
; ignore any error
ProbDealloc:
MOV AX,ErrSwapOut
JMP Exit1;
SwapOk:
;--------------- save origin stack and switch to temporary stack
MOV OriginSP,SP
MOV AX,SS
MOV OriginSS,AX ; save origin stack
MOV AX,SEG TmpStack
MOV SS,AX ; interrupt will be disabled
; for the next command
LEA SP,TmpStack ; use stack in codesegment
; ---------- reduce memory
MOV AX,MyPSP
MOV ES,AX ; ES = MCB
MOV BX,MinSize
MOV AH,4Ah
INT 21h ; set memory to new size
MOV AH,AL
MOV AL,ErrMemReduce
JNC reduceOk
MOV CX,OriginSS
MOV BX,OriginSP
MOV SS,CX
MOV SP,BX
JMP Exit1
reduceOk:
; ---------- exec
PUSH DS
PUSH BP ; save it for TurboPasal
PUSH CS
POP DS
PUSH CS
POP ES ; DS = ES = CS
LEA SI,ProgPathName
LEA DI,nFCB1
MOV AX,2901h
INT 21h
LEA DI,nFCB2
MOV AX,2901h
INT 21h
LEA BX,ExexStruc
LEA DX,ProgPathName
MOV SaveSP,SP ; some DOS versions use ist
MOV SaveSS,SS ; without restoring it
CLD ; some DOS versions need this !
MOV AX,4B00h
INT 21h
MOV SS,SaveSS ; disable interrupt ! until
MOV SP,SaveSP ; next command
JC ExecErr
XOR AX,AX
ExecErr:
POP BP
POP DS
MOV RetValue,AX
; ---------- expand memory
MOV AX,MyPSP
MOV ES,AX
MOV BX,MaxSize
MOV AH,4Ah
INT 21h
JNC ExpandOk
; --- error -> no rescue
MOV AX,4CFFh ; terminate process
INT 21h
ExpandOk:
CASE MethodCS,<SwapInXms,SwapInEMS,SwapInDisk>,isSwapIn
swapInError:
MOV AX,4CFFh ; terminate process
INT 21h
isSwapIn:
MOV AX,RetValue
MOV DosRetValue,AX
MOV CX,AX ; save return value
MOV AX,OriginSS
MOV BX,OriginSP
MOV SS,AX
MOV SP,BX
CASE MethodCS,<XMSDeAllocate,EMSDeAllocate,DiskDeAllocate>,isDeAllocated
JMP EXIT1
deAllocError:
isDeAllocated:
MOV AX,0
Exit1: ;--------------- clear only the stack and exit
POP DS
RET
ENDP
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
SwapInDisk PROC
PUSH DS
; ---------------- set write pointer to beginning of file
MOV AX,4200h ; move file pointer, from start of file
MOV BX,Handle ; Handle number
MOV CX,0
MOV DX,0 ; Offset = 0
INT 21h
; --------------- prepare reading
LES DI,SaveSize ; ES,DI = Size to save
MOV DX,OFFSET SavePoint
MOV AX,SEG SavePoint
MOV DS,AX ; DS,DX = pointer at start
; --------------- read from disk
@@readLoop:
MOV BX,Handle ; Handle number
MOV CX,DosBlockSize ; read max. blocksize
MOV AX,ES
CMP AX,0 ; less then 64k to read ?
JNE @@savemax ; no -> full size
CMP DI,DosBlockSize
JNB @@savemax ; if there is more then one block
MOV CX,DI ; save the rest
@@savemax:
MOV AH,3Fh ; read from a file
PUSH DX
PUSH ES
PUSH DI
INT 21h
POP DI
POP ES
POP DX
JC @@readErr ; error during reading ?
CMP AX,CX ; check if all bytes are read
JNE @@readErr ; error during reading ?
SUB DI,AX ; size to save = size to save - saved
MOV AX,ES
SBB AX,0
MOV ES,AX ; ES,DI = ES,DI - CX = size to read
ADD AX,DI ; ES+DI = 0 -> nothing left to read
CMP AX,0
JE @@ready
MOV AX,DS
ADD AX,DosBlockSize/16 ; next Segment to read
MOV DS,AX
JMP @@readloop
@@ready:
POP DS
MOV AH,3Eh ; close handle
INT 21h
CLC
RET
@@readErr:
; if a error occures, the program must be stopped
MOV AX,4CFFh ; terminate process
INT 21h
ENDP
;--------------------------------------------------------------------------
SwapInEMS PROC
PUSH DS ; save Turbo's DS
PUSH CS
POP DS
PUSH CS
POP ES ; DS = ES = CS
LEA SI,SaveSize
LEA DI,EMSmovStruc.RegionLength
MOVSW
MOVSW ; copy the length
MOV AL,1
STOSB ; copy from EMS
MOV AX,Handle
STOSW
XOR AX,AX
STOSW
STOSW
XOR AX,AX
STOSB ; dest memory type = conventional
STOSW ; handle = 0
MOV AX,OFFSET SavePoint
STOSW
MOV AX,SEG SavePoint
STOSW ; start from "SavePoint"
LEA SI,EMSmovStruc.RegionLength
MOV AX,5700h
INT 67h
POP DS
OR AH,AH
JNZ @@EMSerror
RET
@@EMSerror:
; if a error occures, the program must be stopped
MOV AX,4CFFh ; terminate process
INT 21h
ENDP
;--------------------------------------------------------------------------
SwapInXMS PROC
PUSH DS ; save DS from Turbo Pascal
MOV AX,CS
MOV DS,AX ; DS = CS
MOV ES,AX ; ES = CS
CLD
LEA DI,XMSStructur ; CS:DI = Pointer ad XMS structure
LEA SI,SaveSize ; CS:SI = memory we use
MOVSW ; save size
MOVSW ; in structure
MOV AX,Handle
STOSW ; source handle <> 0 -> XMS
XOR AX,AX
STOSW
STOSW ; offset source = 0
STOSW ; handle destination = 0
MOV AX,OFFSET SavePoint
STOSW
MOV AX,SEG SavePoint
STOSW ; start adress
MOV AH,0Bh ; XMS : "copy block"
LEA SI,XMSStructur ; DS:SI = pointer at structure
CALL XmsPointer ; XMS Call
POP DS
CMP AX,1 ; CY = 0 if equal
JNE @@XMSerror
RET
@@XMSerror:
; if a error occures, the program must be stopped
MOV AX,4CFFh ; terminate process
INT 21h
ENDP
;--------------------------------------------------------------------------
EVEN
SavePoint: ; ******* First point to save **********
;--------------------------------------------------------------------------
; -----------------------------------------
; Variables who are not nedded for swap in
; -----------------------------------------
;-------- variables used for DISK
TmpName DB 256 DUP (?)
;------- variables used for EMS
EVEN
EMSDeviceName: DB 'EMMXXXX0'
;-------- variables used for XMS
XMSStructur XMSstrucTyp ?
; ----------------------------------------------------------------------------
; All functions who are not uses while/after swap out
; ----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
; calculate the bytes to save
;-----------------------------------------------------------------------------
BytesToSave PROC
MOV AX,CS
MOV BX,10h
MUL BX
LEA BX,SavePoint
ADD AX,BX
ADC DX,0 ; DX,AX = first adress to save
PUSH DX
PUSH AX
MOV AX,ES ; AX:CX = last adress as pointer
MOV BX,10H
MUL BX
ADD AX,CX
ADC DX,0 ; DX,AX = last adress as 32 Bit adress
POP BX
POP CX ; CX,BX = first adress as 32 Bit
SUB AX,BX
SBB DX,CX ; DX,AX = Size
RET
CalcErr: MOV AX,0
MOV DX,0
RET
ENDP
;-----------------------------------------------------------------------------
; Copy data from variables in DS to variables in CS and calculate
;-----------------------------------------------------------------------------
CopyFromTurbo PROC
MOV AL,Method
MOV MethodCS,AL
CopyPascalString FileName,ProgPathName ; copy program name in CS
; copy parameters into code segment
PUSH DS
LDS SI,Parameter ; DS:SI -> pointer at parameter
MOV AX,SEG ProgParam
MOV ES,AX
LEA DI,ProgParam ; ES:DI -> pointer at code segment
LODSB ; size of string in AL
STOSB ; copy to CS
CMP AL,0 ; empty string ?
JE @@emptyString
MOV CL,AL
XOR CH,CH ; CX = size
REP_FastMovs ; copy string from DS to CS
@@emptyString:
MOV AL,0Dh ; = CR
STOSB ; last char must be a CR
POP DS ; the old DS
MOV AX,PrefixSeg ; get PSP
MOV MyPSP,AX ; and save it in CS
DEC AX ; the MCB
MOV ES,AX ; ES = MCB
MOV AX,ES:[0003h] ; AX = paragraphs owned now
MOV MaxSize,AX ; save this origin size
; ---- calculate the programs size after swap out
; sP = adress "SavePoint"
; size in byte = OFF (sP) + SEG (sP)*16 - SEG (PSP)*16
; size in parag.= OFF (sP) / 16 + SEG (sP) - SEG (PSP)
; allway round up !
; size in parag.= OFF (sP + 15) / 16 + SEG (sP) - SEG (PSP)
MOV AX,OFFSET (SavePoint+15) ;
MOV CL,4
SHR AX,CL ; AX = AX / 16
ADD AX,SEG SavePoint
SUB AX,MyPSP ; AX = min paragraphs
MOV MinSize,AX
; ------ calculate the size needed to swap out
; ------ must been the last in this function !!!!
LES CX,[LastAdr] ; ES:CX = last adress to save
MOV EnAdress.Segm,ES
MOV EnAdress.Ofst,CX
CALL BytesToSave ; returns in DX,AX size
MOV SaveSize.lo,AX
MOV SaveSize.hi,DX
ADD DX,AX
CMP DX,0 ; size = 0 = error !
RET
ENDP
;-----------------------------------------------------------------------------
INCLUDE FSWAP.INC
;-----------------------------------------------------------------------------
END